#include "excelHandle.h"

ExcelHandle::ExcelHandle(QObject *parent) :
    QObject(parent) {

}

ExcelHandle::~ExcelHandle() {
    exit();
    delete excel;
}

void ExcelHandle::init(bool showWindow, bool showAlert, QString title) {
    excel = new QAxObject;

    excel -> setControl("Excel.Application");
    //显示窗体
    excel -> dynamicCall("SetVisible(bool)", showWindow);
    //不显示任何警告信息
    excel -> setProperty("DisplayAlerts", showAlert);
    //更改 Excel 标题栏
    excel -> setProperty("Caption", title);
}

/**
 * @brief ExcelHandle::save
 * 保存Excel
 */
void ExcelHandle::save(QString url) {
    workbook -> dynamicCall("SaveAs(const QString&)", QDir::toNativeSeparators(url));
}

/**
 * @brief ExcelHandle::exit
 * 释放Excel
 */
void ExcelHandle::exit() {
    //关闭工作簿
    workbook -> dynamicCall("Close()");

    //退出 Excel 程序
    excel -> dynamicCall("Quit()");
}

/**
 * @brief ExcelHandle::openBook
 * 打开工作簿
 */
void ExcelHandle::openBook(QString url) {
    workbooks = excel -> querySubObject("Workbooks");   //获取工作簿集合

    if(QFileInfo(url).exists()) {
        //打开已存在的工作簿
        workbooks -> dynamicCall("Open(const QString&)", QString(url));
    }
    else {
        //添加新的工作簿
        workbooks -> dynamicCall("Add");
    }

    //获取当前已激活的工作簿
    workbook = excel -> querySubObject("ActiveWorkBook");
}

void ExcelHandle::openSheet(int n) {
    //获取当前已激活工作簿的工作表集合
    sheets = workbook -> querySubObject("WorkSheets");

    //选择第 n 个工作表
    sheet = sheets -> querySubObject("Item(int)", n);
}

/**
 * @brief ExcelHandle::addSheet
 * 增加一个Worksheet
 */
void ExcelHandle::addSheet(QString name) {
    //获取工作表数目
    int sheet_count = sheets -> property("Count").toInt();
    QAxObject *last_sheet = sheets -> querySubObject("Item(int)", sheet_count);
    QAxObject *work_sheet = sheets -> querySubObject("Add(QVariant)", last_sheet -> asVariant());
    last_sheet -> dynamicCall("Move(QVariant)", work_sheet -> asVariant());

    //设置工作表名称
    work_sheet -> setProperty("Name", QString("Qt Sheet%1").arg(name));
}

void ExcelHandle::changeBook(QString name) {
    int count = sheets -> property("Count").toInt();

    for(int i = 0; i < count; i ++) {
        sheet = sheets -> querySubObject("Item(int)", i);

        if(sheet -> property("Name") == name) { break; }
    }
}

void ExcelHandle::changeBook(int index) {
    int count = sheets -> property("Count").toInt();

    index = index > count ? count : index;

    sheet = sheets -> querySubObject("Item(int)", index);
}

/**
 * @brief ExcelHandle::deleteSheet
 * 删除一个Worksheet
 */
void ExcelHandle::deleteSheet(QString name) {
    changeBook(name);

    //执行删除当前表操作
    sheet -> dynamicCall("delete");
}

void ExcelHandle::writeData(int col, int row, QVariant data) {
    //选中当前表格的某个单元格
    QAxObject *pRange = sheet -> querySubObject("Cells(int,int)", col, row);

    //向单元格中写入数据
    pRange -> dynamicCall("Value", data);
}

QString ExcelHandle::getEndAddr(QString start_Addr, int col, int row) {
    int temp_col = 0, temp_row, temp_base = 1;
    QString temp_str;
    QRegExp reg_exp_word("^[a-zA-Z]+"),
            reg_exp_num("[0-9]+$");

    //获取列数
    reg_exp_word.indexIn(start_Addr);
    temp_str = reg_exp_word.cap(0);
    for(int i = 0; i < temp_str.length(); i ++) {
        temp_col += (temp_str[temp_str.length() - i - 1].unicode() - 'A' + 1) * temp_base;
        temp_base *= 26;
    }
    temp_col += col;

    //还原列号
    temp_str = "";
    while(temp_col > 1) {
        temp_str = QString("%1%2").arg(static_cast<char>(temp_col % 26 + 'A' - 1)).arg(temp_str);

        temp_col /= 26;
    }

    //获取函数
    reg_exp_num.indexIn(start_Addr);
    temp_row = reg_exp_num.cap(0).toInt();
    temp_row += row;

    return QString("%1%2").arg(temp_str).arg(temp_row);
}

void ExcelHandle::writeDataSet(QString start_Addr, QList<QList<QVariant>> data_Set) {
    //定义两个中转变量，res 用于二次列表接收，temp 用于一次列表接收
    QList<QVariant> res, temp;

    for(int i = 0; i < data_Set.length(); i ++) {
        //清空一次接收列表
        temp.clear();

        //第一次循环将数据注入列表
        for(int j = 0; j < data_Set[0].length(); j ++) {
            temp.append(data_Set[i][j]);
        }

        //第二次循环将数据注入列表
        res.append(QVariant(temp));
    }

    QString end_addr = getEndAddr(start_Addr, data_Set[0].length() - 1, data_Set.length() - 1);

    //生成数据填充范围
    QString range = QString("range(%1:%2)").arg(start_Addr).arg(end_addr);

    //确认数据填充范围
    QAxObject *usedRange = sheet -> querySubObject(range.toUtf8().data());
    //根据填充范围填充数据
    usedRange -> setProperty("Value", QVariant(res));
}

QList<QList<QVariant>> ExcelHandle::readData() {
    //获取被使用的表格对象
    usedRange = sheet -> querySubObject("UsedRange");

    //获取被使用的表格对象中的结果集
    QVariant v = usedRange -> dynamicCall("Value");

    //将结果集转换为一维列表
    QList<QVariant> vl = v.toList();

    //定义一个二维列表用于存放最终结果集
    QList<QList<QVariant>> vll;

    //使用循环将一维列表转换为二维列表
    for(int i = 0; i < vl[0].toList().size(); i ++) {
        vll.append(vl[i].toList());
    }

    //返回一个二维列表
    return vll;
}
